//! 基本节点
//!

use crate::bean::node::{node_status::NodeStatus, node_type::NodeType};
use serde::{Deserialize, Serialize};

#[derive(Debug, Clone, Default, Serialize, Deserialize, Eq, PartialEq)]
pub struct BaseNode {
    node_type: NodeType, // 节点类型
    status: NodeStatus,  // 节点状态
    public_key: String,  // 公钥
    address: String,     // 收款地址
    ip: String,          // 公网IP
    rpc_port: i32,       // rpc服务端口
    http_port: i32,      // http服务端口
    url: String,         // http服务域名
}

#[derive(Debug, Clone, Default)]
pub struct BaseNodeBuilder {
    node_type: NodeType, // 节点类型
    status: NodeStatus,  // 节点状态
    public_key: String,  // 公钥
    address: String,     // 收款地址
    ip: String,          // 公网IP
    rpc_port: i32,       // rpc服务端口
    http_port: i32,      // http服务端口
    url: String,         // http服务域名
}
impl BaseNode {
    pub fn new() -> BaseNodeBuilder {
        BaseNodeBuilder::default()
    }

    pub fn node_type(&self) -> NodeType {
        self.node_type
    }

    pub fn status(&self) -> NodeStatus {
        self.status
    }

    pub fn public_key(&self) -> &str {
        &self.public_key
    }

    pub fn address(&self) -> &str {
        &self.address
    }

    pub fn ip(&self) -> &str {
        &self.ip
    }

    pub fn rpc_port(&self) -> i32 {
        self.rpc_port
    }

    pub fn http_port(&self) -> i32 {
        self.http_port
    }

    pub fn url(&self) -> &str {
        &self.url
    }

    pub fn set_node_type(&mut self, node_type: NodeType) {
        self.node_type = node_type;
    }

    pub fn set_status(&mut self, status: NodeStatus) {
        self.status = status;
    }

    pub fn set_public_key(&mut self, key: &str) {
        self.public_key = key.to_string();
    }

    pub fn set_address(&mut self, addr: &str) {
        self.address = addr.to_string();
    }

    pub fn set_ip(&mut self, ip: &str) {
        self.ip = ip.to_string();
    }

    pub fn set_rpc_port(&mut self, port: i32) {
        self.rpc_port = port;
    }

    pub fn set_http_port(&mut self, port: i32) {
        self.http_port = port;
    }

    pub fn set_utl(&mut self, url: &str) {
        self.url = url.to_string();
    }

    pub fn check_if_wait_consensus_node(&self) -> bool {
        match self.status {
            NodeStatus::WaitConsensus
            | NodeStatus::WaitUpdateInConsensus
            | NodeStatus::WaitUpdateHasConsensused
            | NodeStatus::WaitDeleteInConsensus
            | NodeStatus::WaitDeleteHasConsensused => true,
            _ => false,
        }
    }

    pub fn check_if_consensus_node(&self) -> bool {
        match self.status {
            NodeStatus::WaitUpdateHasConsensused
            | NodeStatus::UpdattingHasConsensused
            | NodeStatus::HasConsensused
            | NodeStatus::HasShareded => true,
            _ => false,
        }
    }
}

impl BaseNodeBuilder {
    pub fn node_type(&mut self, node_type: NodeType) -> &mut Self {
        self.node_type = node_type;
        self
    }

    pub fn status(&mut self, status: NodeStatus) -> &mut Self {
        self.status = status;
        self
    }

    pub fn public_key(&mut self, key: &str) -> &mut Self {
        self.public_key = key.to_string();
        self
    }

    pub fn address(&mut self, add: &str) -> &mut Self {
        self.address = add.to_string();
        self
    }

    pub fn ip(&mut self, ip: &str) -> &mut Self {
        self.ip = ip.to_string();
        self
    }

    pub fn rpc_port(&mut self, port: i32) -> &mut Self {
        self.rpc_port = port;
        self
    }

    pub fn http_port(&mut self, port: i32) -> &mut Self {
        self.http_port = port;
        self
    }

    pub fn url(&mut self, url: &str) -> &mut Self {
        self.url = url.to_string();
        self
    }

    pub fn build(self) -> BaseNode {
        BaseNode {
            node_type: self.node_type,
            status: self.status,
            public_key: self.public_key,
            address: self.address,
            ip: self.ip,
            rpc_port: self.rpc_port,
            http_port: self.http_port,
            url: self.url,
        }
    }
}
